// Copyright 2007 Google, Inc. All Rights Reserved.

package com.google.jessewilson.codesearch.intellij.dfs;

import com.google.jessewilson.codesearch.api.CodeFile;
import com.google.jessewilson.codesearch.io.IO;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jetbrains.annotations.NotNull;

/**
 * @author jessewilson
 */
public class DownloadedFile extends VirtualFile {

  private final DownloadedFileSystem fileSystem;
  private final DownloadedDirectory parent;

  private final CodeFile codeFile;
  private final File localFile;

  DownloadedFile(DownloadedFileSystem fileSystem, DownloadedDirectory parent,
      CodeFile codeFile, File localFile) {
    assert(fileSystem != null);
    assert(codeFile != null);
    assert(localFile != null);

    this.fileSystem = fileSystem;
    this.parent = parent;

    this.codeFile = codeFile;
    this.localFile = localFile;
  }

  public CodeFile getCodeFile() {
    return codeFile;
  }

  public String getName() {
    return codeFile.getPath().getFileName();
  }

  public VirtualFileSystem getFileSystem() {
    return fileSystem;
  }

  public String getPath() {
    return codeFile.getPath().toString();
  }

  public boolean isWritable() {
    return false;
  }

  public boolean isDirectory() {
    return false;
  }

  public boolean isValid() {
    return true;
  }

  public VirtualFile getParent() {
    return parent;
  }

  public VirtualFile[] getChildren() {
    return null;
  }

  public OutputStream getOutputStream(Object requestor,
      long newModificationStamp, long newTimeStamp) throws IOException {
    throw new UnsupportedOperationException("file not writable");
  }

  public byte[] contentsToByteArray() throws IOException {
    return IO.readFully(getInputStream());
  }

  @Override
  public long getModificationStamp() {
    if (codeFile.getUpdated() != null) {
      return codeFile.getUpdated().getTime();
    } else {
      return 0;
    }
  }

  public long getTimeStamp() {
    if (codeFile.getUpdated() != null) {
      return codeFile.getUpdated().getTime();
    } else {
      return 0;
    }
  }

  public long getLength() {
    try {
      return contentsToByteArray().length;
    } catch (IOException e) {
      Logger.getLogger(DownloadedFile.class.getName()).log(
          Level.WARNING, "Failed to get length of file " + codeFile, e);
      return 0;
    }
  }

  public void refresh(boolean asynchronous, boolean recursive,
      Runnable postRunnable) {
    // do nothing
  }

  public InputStream getInputStream() throws IOException {
    return new FileInputStream(localFile);
  }

  @NotNull public String getUrl() {
    return getPath();
  }
}
